P0 KV-Server

Part 0

In this Key-Value Database Server Project, the following functions will be implemented:

Part 1 Components

The keyValueServer is the struct that act as a server and control the concurrent access of data from multiple clients.

type keyValueServer struct {
	listener     net.Listener
	queries      chan *Query
	connections  chan net.Conn
	clients      []*Client
	db           kvstore.KVStore
	count_active chan int      // Channel to receive active client count
	close_signal chan struct{} // Channel to signal the server shutdown
	closed       bool
}

The listener is the socket that listens the connection from incoming clients. The clients is a array for the client that ever been connected. the db is the where data stored, who has Put(), Get(), Delete(), Update() functions to operates data. connections is a chan that convey the coming connection that listener accepts to the go routine (workLoop) clients[] stores. count_active is the chan that return the count result from the workLoop to the CountActive function return. The queries is a chan for queries processing. When the parseLoop finish a parse, and pass the query struct to the queries chan for the workLoop to handle later.

Query struct is used to describe what the task is from client.

type Query struct {
	key       string
	value     string
	queryType string
	client    *Client
	value_new string
}

The buffer chan in Client struct is used to store the return value for the Get() function called by client.

type Client struct {
	connection net.Conn
	alive      int
	closed     chan struct{} // Used to signal the closure of the client
	buffer     chan []byte   // Buffered channel to queue messages
}

Part 2 Go Routines

After the Start() function was called, the kvs starts with acceptClient() and workLoop() two Go routine start. Whenever a new connection establishes, the kvs.connections chan will be sent with a message and a new Client will born in the clients array. Meanwhile, the readFromClient() and writeToClient() Go routine will start. Whenever a request message is received by readFromClient() , the parsed Query will be send to the kvs workLoop, waiting for process. The buffer chan is used to keep data.

To address the slow reader problem, using a condition for the buffer to send client data.

if len(query.client.buffer) < maxBufferSize {
	query.client.buffer <- buffer.Bytes()
}

When a Close() is called, the close_signal chan will be close and all the Go routine with this chan selected, will be noticed and return the go routine.

The CountActive() is simply a query to handle in the workLoop.

Eventually, the KV server is implemented.